#include <string>
#include <cxxabi.h>
using namespace std;

#define GET_TYPENAME(expr) abi::__cxa_demangle(typeid(expr).name(), nullptr, nullptr, nullptr)

template<typename T>
const T &GetMax(const T &a, const T &b) {
    printf("T = %s\n", GET_TYPENAME(T));
    return a > b ? a : b;
}

template <typename T>
void f(T a, T b) {
    printf("T = %s\n", GET_TYPENAME(T));
}

int main() {
    string s1 = "abc";
    const string s2 = "def";
    f(s1, s2); //在拷贝时顶层const会被忽略
    int a[3], b[4];
    f(a, b); //数组会被转换为指针类型
    printf("%d\n", GetMax(3, 5)); //编译器推导出T=int
    printf("%d\n", GetMax<int>(3, 5)); //显示实例化T=int
    printf("%f\n", GetMax(3.0, 5.0)); //编译器推导出T=double
    printf("%f\n", GetMax<double>(3.0, 5.0)); //显示实例化T=double
    // printf("%f\n", GetMax(3, 5.0)); //编译器报错，无法推导
    printf("%f\n", GetMax<double>(3, 5.0)); //显示指定类型后编译器会对形参进行隐式类型转换
}